package com.example.aidlclient;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.example.ipctest.Book;
import com.example.ipctest.IBookManager;
import com.example.ipctest.IOnNewBookArrivedListener;

import java.util.List;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private IBookManager iBookManager;

    private static final int MESSAGE_NEW_BOOK_ARRIVED = 100;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MESSAGE_NEW_BOOK_ARRIVED:
                    Log.e(TAG, "handleMessage: receive new book:" + msg.obj);
                    break;
            }
        }
    };

    private ServiceConnection mConnection = new ServiceConnection() {
        /**
         * 连接Service成功以后的回调方法
         * @param name
         * @param service Service中onBind返回的对象，其实就是Service中ADIL接口的内部类Stub的实现类对象
         */
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG, "onServiceConnected: ");
            /**
             * 当Service不在当前进程时，IBookManager.Stub.asInterface(service)返回的是一个Proxy对象
             * 该对象是IBookManager.Stub的内部类，本身实现了IBookManager接口
             */
             iBookManager = IBookManager.Stub.asInterface(service);
            try {
                /**
                 * 这里的iBookManager其实是个Proxy对象，调用的就是Proxy中的getBookList，在这里面通过调用IBinder的transate方法,完成远程过程调用
                 * 但是，当调用该方法时，当前线程会挂起，等待远程过程调用完成后，才能继续当前线程，
                 * 所以如果远程调度过程有可能是耗时的，则可能导致当前线程长时间阻塞，考虑用子线程
                 */
                List<Book> bookList = iBookManager.getBookList(1);
                if (bookList != null) {
                    int size = bookList.size();
                    Log.e(TAG, "bookList " + bookList.toString());
                    for (int i = 0; i < size; i++) {
                        Book book = bookList.get(i);
                        Log.e(TAG, "bookName=" + book.name);
                    }
                }

                iBookManager.registerLisenter(mOnNewBookArrivedListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_startservice).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bindService();
            }
        });
        findViewById(R.id.btn_toast).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "Hello Word!", Toast.LENGTH_SHORT).show();
            }
        });


    }

    private void bindService() {
        Intent intent = new Intent();
        intent.setAction("com.example.ipctest.BookManagerService");
        intent.setPackage("com.example.ipctest");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    /**
     * 注册到服务端的AIDL接口的实现对象，供服务端回调客户端方法
     * 其实是IOnNewBookArrivedListener.Stub()对象，和服务端onBind返回的对象是类似的
     */
    private IOnNewBookArrivedListener mOnNewBookArrivedListener = new IOnNewBookArrivedListener.Stub(){

        /**
         * 该方法运行在客户端的Binder线程池中，所以如果想更新UI，需要切换到主线程
         * @param book 实现了Parcelable的对象
         * @throws RemoteException
         */
        @Override
        public void onNewBookArrived(Book book) throws RemoteException {
            Log.e(TAG, "onNewBookArrived thread name:" + Thread.currentThread().getName());
            mHandler.obtainMessage(MESSAGE_NEW_BOOK_ARRIVED, book).sendToTarget();
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            if (iBookManager != null && iBookManager.asBinder().isBinderAlive()) {
                iBookManager.unRegisterLisenter(mOnNewBookArrivedListener);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        unbindService(mConnection);
    }
}
